import asyncio
import socket
import http.client
import sys

# 已知端口和服务名称的映射表
known_services = {
    5678: 'rrac',
    80: 'http',  # Example: HTTP service
    # Add more known services here
}

async def scan_port(host, port):
    try:
        reader, writer = await asyncio.open_connection(host, port)
        writer.close()
        await writer.wait_closed()
        if port in known_services:
            service = known_services[port]
            if service == 'http':
                version = await get_http_version(host, port)
                service = f"HTTP ({version})"
        else:
            try:
                service = socket.getservbyport(port)
            except OSError:
                service = 'Unknown'
        
        # Check if the port is open before returning
        return port, service
    except (ConnectionRefusedError, asyncio.TimeoutError):
        return port, None

async def scan_ports(host, port_range):
    open_ports = []
    tasks = [scan_port(host, port) for port in range(port_range[0], port_range[1] + 1)]
    for task in asyncio.as_completed(tasks):
        port, service = await task
        if service is not None:
            open_ports.append((port, service))
    return open_ports

async def get_http_version(host, port):
    try:
        conn = http.client.HTTPConnection(host, port)
        conn.request("HEAD", "/")
        res = conn.getresponse()
        headers = res.getheaders()
        for header in headers:
            if header[0].lower() == 'server':
                return header[1]
    except Exception as e:
        pass
    return 'Unknown'

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Usage: python3 Port_scanning.py <host> <start_port> <end_port>")
        sys.exit(1)
    
    host = sys.argv[1]
    port_start = int(sys.argv[2])
    port_end = int(sys.argv[3])

    open_ports = asyncio.run(scan_ports(host, (port_start, port_end)))
    if open_ports:
        print(f"Open ports on {host}:")
        for port, service in open_ports:
            print(f"Port {port}: {service}")
    else:
        print(f"No open ports found on {host} within range {port_start}-{port_end}.")

# pip install http.client
# sansjtw